package ua.kharkov.knure.pereverziev.diploma.i18n;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

/**
 * I18n support.
 * 
 * @author A.Pereverziev
 * 
 */
public class RManager {
	private static Map<Locale, ResourceBundle> bundles;

	private static Map<String, Locale> locales;

	private static String defaultLocaleName;

	private static RManager instance;

	private static synchronized RManager getInstance() {
		checkInititalization();
		return instance;
	}

	/**
	 * Creates the RManager instance.
	 * 
	 * @param bundleName
	 *            The bundle name.
	 * @param localeNames
	 *            The string containing locale names. The first locale is the
	 *            default one.
	 */
	private RManager(String bundleName, String localeNames) {
		bundles = new HashMap<Locale, ResourceBundle>();
		locales = new LinkedHashMap<String, Locale>();

		boolean isFirst = true;
		// go through all locale names
		StringTokenizer st = new StringTokenizer(localeNames, " ");
		while (st.hasMoreTokens()) {
			String localeName = st.nextToken().trim();
			Locale locale = getLocale(localeName);
			locales.put(localeName, locale);
			bundles.put(locale, ResourceBundle.getBundle(bundleName, locale));

			if (isFirst) {
				isFirst = false;
				defaultLocaleName = locale.toString();
			}
		}

		bundles.put(new Locale("ua"), ResourceBundle.getBundle("messages"));
	}

	/**
	 * Returns the locale with the given name.
	 * 
	 * @param localeName
	 *            The name of the locale.
	 * @return Locale object.
	 */
	private Locale getLocale(String localeName) {
		String language = "";
		String country = "";
		String variant = "";

		StringTokenizer parts = new StringTokenizer(localeName, "_");
		if (parts.hasMoreTokens())
			language = parts.nextToken().toLowerCase();
		if (parts.hasMoreTokens())
			country = parts.nextToken().toUpperCase();
		if (parts.hasMoreTokens())
			variant = parts.nextToken();

		if (language.isEmpty())
			throw new IllegalArgumentException(
					"Cannot create locale with the empty name");

		return new Locale(language, country, variant);
	}

	/**
	 * Initializes RManager.
	 * 
	 * @param localeNames
	 *            String with locale names.
	 */
	public static synchronized void init(String bundleName, String localeNames) {
		if (instance != null)
			throw new IllegalStateException(
					"RBundleContainer already initialized");
		instance = new RManager(bundleName, localeNames);
	}

	/**
	 * Returns resource bundles container.
	 */
	public static Map<Locale, ResourceBundle> getBundles() {
		checkInititalization();
		return bundles;
	}

	/**
	 * Returns locales container.
	 */
	public static Map<String, Locale> getLocales() {
		checkInititalization();
		return locales;
	}

	private String getString(String key, Locale locale) {
		return bundles.get(locale).getString(key);
	}

	/**
	 * Returns a property value by its key and locale.
	 * 
	 * @param key
	 *            Property key.
	 * @param locale
	 *            Locale.
	 * @return Property value.
	 */
	public static String getProperty(String key, Locale locale) {
		checkInititalization();
		return getInstance().getString(key, locale);
	}

	/**
	 * Returns a property value by its key and locale name.
	 * 
	 * @param key
	 *            Property key.
	 * @param localeName
	 *            Locale name.
	 * @return Property value.
	 */
	public static String getProperty(String key, String localeName) {
		return getInstance().getString(key, getLocales().get(localeName));
	}

	public static String getDefaultLocaleName() {
		checkInititalization();
		return defaultLocaleName;
	}

	private static void checkInititalization() {
		if (instance == null)
			throw new IllegalStateException(
					"RManager must be initialized with RManager.init method first");
	}

}